package logic;

import java.util.Vector;

public class TexasHoldemGame extends Thread {
	private Vector<TexasHoldemPlayer> matchPlayerList;
	private Vector<TexasHoldemPlayer> CompletePlayerList;
	private TexasHoldemTable table;
	private Deck deck;

	private int actualPlayer;
	private float blind;
	private float actualBet;
	
	private int dealer;
	private int smallBlind;
	private int bigBlind;	
	private int lastRaise;
	
	private int bettingRound;
	private int winner;
	
	public TexasHoldemGame(float startBlind) {
		CompletePlayerList = new Vector<TexasHoldemPlayer>();
		matchPlayerList = new Vector<TexasHoldemPlayer>();
		table = new TexasHoldemTable();
		deck = new Deck();
		blind = startBlind;
		dealer = 0;
	}

	@Override
	public void start() {
		if(CompletePlayerList.size() < 2) {
			//Throw some exception
		}
		
		getActualPlayer();		
		startNewGame();
	}

	private void getActualPlayer() {
		if(CompletePlayerList.size() == 2) {
			if(dealer == 1) {
				actualPlayer = 0;
			}else {
				actualPlayer = 1;
			}
		} else if(CompletePlayerList.size() == 3) {
			actualPlayer = dealer;
		} else {
			if(dealer+2 > CompletePlayerList.size()) {
				 actualPlayer = 2;
			} else if(dealer+3 > CompletePlayerList.size()){
				actualPlayer = 1;
			} else if(dealer+4 > CompletePlayerList.size()){
				actualPlayer = 0;
			} else {
				actualPlayer = dealer+3;
			}
		}		
	}

	private void startNewGame() {
		matchPlayerList.removeAllElements();
		matchPlayerList.addAll(CompletePlayerList);

		actualBet = blind;
		winner = -1;
		bettingRound = 1;
		table.cleanSlot();
		table.clearPot();
		
		if(dealer+2 > matchPlayerList.size()) {
			smallBlind = 0;
			bigBlind = 1;
			if(bigBlind+2 > matchPlayerList.size()) {
				lastRaise = 0;
			}else {
				lastRaise = 2;
			}
		} else if(dealer+3 > matchPlayerList.size()){
			smallBlind = dealer+1;
			bigBlind = 0;
			lastRaise = 1;			
		} else {
			smallBlind = dealer+1;
			bigBlind = dealer+2;
			if(bigBlind+2 > matchPlayerList.size()) {
				lastRaise = 0;
			}else {
				lastRaise = bigBlind+1;
			}
		}
		
		matchPlayerList.get(smallBlind).bet(blind/2);
		table.addToPot(blind/2);
		matchPlayerList.get(bigBlind).bet(blind);
		table.addToPot(blind);
		
		for(TexasHoldemPlayer p : matchPlayerList) {
			p.clearCards();
			p.addCard(deck.getCard());
			p.addCard(deck.getCard());
		}
	}

	public void addNewPlayer(TexasHoldemPlayer player) {
		CompletePlayerList.add(player);
	}

	public TexasHoldemPlayer getPlayer() {
		if(actualPlayer > -1) {
			return matchPlayerList.get(actualPlayer);
		}
		
		return null;
	}

	public boolean playerCall() {
		float lastBet = matchPlayerList.get(actualPlayer).getLastBet();
			 
		if( lastBet < actualBet) {
			if(matchPlayerList.get(actualPlayer).bet(actualBet-lastBet)) {
				table.addToPot(actualBet-lastBet);
			}else {
				return false;
			}
		}
		
		increaseActualPlayer();
		nextPlayer();
		
		return true;
	}

	public boolean playerRaise(float f) {
		float lastBet = matchPlayerList.get(actualPlayer).getLastBet();
		
		if(matchPlayerList.get(actualPlayer).bet(actualBet-lastBet+f)) {			
			lastRaise = actualPlayer;
			actualBet += f;
			table.addToPot(actualBet-lastBet);
			
			increaseActualPlayer();
			nextPlayer();
			return true;
		}
		
		return false;
	}

	public void playerFold() {
		matchPlayerList.remove(actualPlayer);
		if(actualPlayer+1>matchPlayerList.size()) {
			increaseActualPlayer();			
		}		
		
		nextPlayer();
	}

	private void nextPlayer() {
		
		if(actualPlayer == lastRaise) {
			if(bettingRound < 4) {
				//fim da rodada
				actualPlayer = smallBlind;
				lastRaise = smallBlind;
				actualBet = 0.0f;
				
				//reset all lastbets
				for(TexasHoldemPlayer p : matchPlayerList) {
					p.resetLastBet();
				}
				
				if(bettingRound == 1){
					table.addCardToSlot(deck.getCard());
					table.addCardToSlot(deck.getCard());
					table.addCardToSlot(deck.getCard());
				}else {
					table.addCardToSlot(deck.getCard());
				}
				bettingRound++;
			}else {
				//fim do jogo
				actualPlayer = -1;
			}
		}else if(matchPlayerList.size() == 1) {
			//fim do jogo
			actualPlayer = -1;
			winner = 0;
			matchPlayerList.get(winner).addMoney(table.showPot());
		}
	}

	private void increaseActualPlayer() {
		if((actualPlayer + 2) > matchPlayerList.size()) {
			actualPlayer = 0;
		} else {
			actualPlayer++;
		}
	}

	public String showSlot() {
		return table.showSlot();
	}

	public float showPot() {
		return table.showPot();
	}

	public TexasHoldemPlayer getWinner() {
		return matchPlayerList.get(winner);
	}

	public void nextMatch(float newBlind) {
		blind = newBlind;
		
		if((dealer + 2) > CompletePlayerList.size()) {
			dealer = 0;
		} else {
			dealer++;
		}
		
		getActualPlayer();
		startNewGame();
	}

}
